/*
 * MIT License
 *
 * Copyright (c) 2023 北京凯特伟业科技有限公司
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package com.je.common.base.office.service;

import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.je.common.base.DynaBean;
import com.je.common.base.cache.office.OfficeCacheManager;
import com.je.common.base.cache.office.OfficeDataCacheManager;
import com.je.common.base.constants.dd.DDType;
import com.je.common.base.document.InternalFileBO;
import com.je.common.base.mapper.query.NativeQuery;
import com.je.common.base.office.util.OfficeUtil;
import com.je.common.base.office.vo.FileVO;
import com.je.common.base.office.vo.JeOfficeVo;
import com.je.common.base.office.vo.OfficeDataVo;
import com.je.common.base.service.DataSourceRpcService;
import com.je.common.base.service.MetaResourceService;
import com.je.common.base.service.MetaService;
import com.je.common.base.service.rpc.BeanService;
import com.je.common.base.service.rpc.DocumentInternalRpcService;
import com.je.common.base.spring.SpringContextHolder;
import com.je.common.base.util.*;
import com.je.common.base.workflow.service.CurrentUserTaskRpcService;
import com.je.common.base.workflow.vo.CirculationHistoryVo;
import com.je.common.base.workflow.vo.CommentVo;
import com.je.core.entity.extjs.JSONTreeNode;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.*;

@Component("jeOfficeService")
public class JeOfficeServiceImpl implements JeOfficeService {
    @Autowired
    private MetaService metaService;
    @Autowired
    private DocumentInternalRpcService documentInternalRpcService;
//    @Autowired
//    private WfHistoryManager wfHistoryManager;
//    @Autowired
//    private SealService sealService;
    @Autowired
    private OfficeCacheManager officeCacheManager;
    @Autowired
    private OfficeDataCacheManager officeDataManager;
    @Autowired
    private BeanService beanService;
    @Autowired
    private MetaResourceService metaResourceService;
    @Autowired
    private DataSourceRpcService dataSourceRpcService;
    @Autowired
    private JeWordService jeWordService;
    @Autowired
    private JeExcelService jeExcelService;
    @Autowired
    private JePdfService jePdfService;
    @Autowired
    private CurrentUserTaskRpcService currentUserTaskRpcService;
    @Autowired
    private JeSealService jeSealService;

    @Override
    public JeOfficeVo doExecDoc(String code, HashMap<String, Object> params) {
        return doExecDoc(code,params,false);
    }

    @Override
    public JeOfficeVo doExecDoc(String code, HashMap<String, Object> params, Boolean convertPdf) {
        HashMap<String,String> requestParams=new HashMap<>();
        for(String key:params.keySet()){
            String val=params.get(key)+"";
            if(StringUtil.isEmpty(val)){
                val="";
            }
            requestParams.put(key,val);
        }
        JeOfficeVo jeOfficeVo = getOfficeVo(code, requestParams);
        //执行数据源取值
        doExecData(jeOfficeVo);
        doExecEvent(jeOfficeVo,"init");
        //执行文档转换
        JSONObject returnObj = new JSONObject();
        returnObj.put("success",true);
        returnObj.put("obj","执行成功");
        if ("word".equals(jeOfficeVo.getType())) {
            jeWordService.doExecOffice(jeOfficeVo,returnObj);
        } else if ("excel".equals(jeOfficeVo.getType())) {
            jeExcelService.doExecOffice(jeOfficeVo,returnObj);
        } else if ("pdf".equals(jeOfficeVo.getType())) {
            jePdfService.doExecOffice(jeOfficeVo,returnObj);
        }
        return jeOfficeVo;
    }

    @Override
    public DynaBean getDoc(String code, String refresh) {
        DynaBean doc= officeCacheManager.getCacheValue(code);
        if("1".equals(refresh)){
            doc=null;
        }
        if(doc==null) {
            doc=metaResourceService.selectOneByNativeQuery("JE_OFFICE_DOC",NativeQuery.build().eq("DOC_CODE",code));
            List<DynaBean> docDs = metaResourceService.selectByTableCodeAndNativeQuery("JE_OFFICE_DOCDS", NativeQuery.build().eq("JE_OFFICE_DOC_ID",doc.getStr("JE_OFFICE_DOC_ID")).orderByAsc("SY_ORDERINDEX"));
            doc.set("_DOCDS_", docDs);
            officeCacheManager.putCache(code,doc);
        }
        return doc;
    }

    @Override
    public DynaBean getDocDs(String code, String refresh) {
        DynaBean data= officeDataManager.getCacheValue(code);
        if("1".equals(refresh)){
            data=null;
        }
        if(data==null) {
            data=metaResourceService.selectOneByNativeQuery("JE_OFFICE_DATA", NativeQuery.build().eq("DATA_CODE",code));
            List<DynaBean> fields = metaResourceService.selectByTableCodeAndNativeQuery("JE_OFFICE_FIELD",  NativeQuery.build().eq("JE_OFFICE_DATA_ID",data.getStr("JE_OFFICE_DATA_ID")).orderByAsc("SY_ORDERINDEX"));
            for(DynaBean field:fields){
                field.set("_DSCODE_",code);
            }
            data.set("_FIELDS_", fields);
            officeDataManager.putCache(code,data);
        }
        return data;
    }

    @Override
    public JeOfficeVo getOfficeVo(String code, HashMap<String, String> requestParams) {
        DynaBean doc=getDoc(code,"1");
        List<DynaBean> docDss= (List<DynaBean>) doc.get("_DOCDS_");
        JeOfficeVo officeVo=new JeOfficeVo();
        officeVo.setName(doc.getStr("DOC_NAME"));
        officeVo.setCode(doc.getStr("DOC_CODE"));
        officeVo.setFile(doc.getStr("DOC_FILE"));
        if(StringUtil.isNotEmpty(officeVo.getFile())){
            String fileName=officeVo.getFile().split("\\*")[0];
            officeVo.setFileSuffix(OfficeUtil.getFileTypeSuffix(fileName));
        }
        officeVo.setType(doc.getStr("DOC_FILETYPE_CODE"));
        officeVo.setReturnType(doc.getStr("RETURN_TYPE"));
        officeVo.setDocConfig(doc);
        officeVo.setTitle(requestParams.get("title"));
        officeVo.setFileName(requestParams.get("fileName"));
        if(StringUtil.isEmpty(officeVo.getFileName()) && StringUtil.isNotEmpty(doc.getStr("DOC_FILENAME"))){
            String fileName= StringUtil.parseKeyWord(doc.getStr("DOC_FILENAME",""),requestParams.entrySet());
            officeVo.setFileName(fileName);
        }
        if(StringUtil.isNotEmpty(doc.getStr("DOC_BZRULE"))){
            String bz= StringUtil.parseKeyWord(doc.getStr("DOC_BZRULE",""),requestParams.entrySet());
            officeVo.setBz(bz);
        }
        officeVo.setRequestParams(requestParams);
        officeVo.setJeWordRows(new HashSet<>());
        if(StringUtil.isNotEmpty(requestParams.get("returnType"))){
            officeVo.setReturnType(requestParams.get("returnType"));
        }
        List<OfficeDataVo> officeDataVos=new ArrayList<>();
        for(DynaBean docDs:docDss){
            DynaBean docData=getDocDs(docDs.getStr("DATA_CODE"),"1");
            List<DynaBean> fields= (List<DynaBean>) docData.get("_FIELDS_");
            List<DynaBean> toFields=new ArrayList<>();
            for(DynaBean field:fields){
                toFields.add(field.clone());
            }
            OfficeDataVo officeDataVo=new OfficeDataVo();
            officeDataVo.setName(docData.getStr("DATA_NAME"));
            officeDataVo.setCode(docData.getStr("DATA_CODE"));
            officeDataVo.setType(docData.getStr("DATA_TYPE"));
            officeDataVo.setDocDs(docDs);
            officeDataVo.setDsBean(docData);
            officeDataVo.setFields(toFields);
            officeDataVos.add(officeDataVo);
        }
        officeVo.setOfficeDatas(officeDataVos);
        return officeVo;
    }

    @Override
    public void doExecData(JeOfficeVo jeOfficeVo) {
        Map<String, List<DynaBean>> dzValues=new HashMap<>();
        //声明关键字
        //默认值信息
        Set<Map.Entry<String,String>> ddSet = new HashSet<>();
        //加入登录信息
        ddSet.addAll(OfficeUtil.getMapVals(SecurityUserHolder.getCurrentInfo()).entrySet());
//        //加入用户变量
//        ddSet.addAll(FrontCacheManager.getCacheValues().entrySet());
//        ddSet.addAll(BackCacheManager.getCacheValues().entrySet());
        //加入系统设置
//        ddSet.addAll(WebUtils.getAllSysVar().entrySet());
        ddSet.addAll(jeOfficeVo.getRequestParams().entrySet());
        HashMap<String, String>  dsParams=jeOfficeVo.getRequestParams();
        for(OfficeDataVo officeData:jeOfficeVo.getOfficeDatas()){
            DynaBean dsBean=officeData.getDsBean();
            //提取方式
            String tqfs=dsBean.getStr("DATA_TQFS_CODE");
            List<DynaBean> lists=new ArrayList<>();
            if("TABLE".equals(tqfs)){
                String tableCode=dsBean.getStr("DATA_TABLECODE");
                String whereSql=dsBean.getStr("DATA_WHERESQL");
                String orderSql=dsBean.getStr("DATA_ORDERSQL");
                if(StringUtil.isNotEmpty(whereSql)){
                    whereSql= StringUtil.parseKeyWord(whereSql,ddSet);
                }
                if(StringUtil.isNotEmpty(orderSql)){
                    whereSql+=(" "+orderSql);
                }
                lists=metaService.selectBeanSql(tableCode,whereSql);
            }else if("SQL".equals(tqfs)){
                String sql=dsBean.getStr("DATA_SQL");
                if(StringUtil.isNotEmpty(sql)){
                    sql= StringUtil.parseKeyWord(sql,ddSet);
                }
                List<Map<String,Object>> datas=metaService.selectSql(sql,new Object[]{});
                if(datas!=null) {
                    for (Map dataObj : datas) {
                        DynaBean bean=new DynaBean();
                        for(Object keyObj:dataObj.keySet()){
                            String key=keyObj+"";
                            if(StringUtil.isNotEmpty(key)){
                                bean.set(key,dataObj.get(key));
                            }
                        }
                        lists.add(bean);
                    }
                }
            }else if("DIY".equals(tqfs)){
                String beanName=dsBean.getStr("DATA_BEAN");
                String beanMethod=dsBean.getStr("DATA_METHOD");
                if(StringUtil.isNotEmpty(beanName) && StringUtil.isNotEmpty(beanMethod)) {
                    Object bean = SpringContextHolder.getBean(beanName);
                    lists= (List<DynaBean>) ReflectionUtils.getInstance().invokeMethod(bean, beanMethod, new Object[]{jeOfficeVo});
                }
            }else if("URL".equals(tqfs)){
                String url=dsBean.getStr("DATA_URL");
                JSONArray urlParamArrays= JSONArray.parseArray(dsBean.getStr("DATA_PARAM","[]"));
                Map<String,Object> urlParams=new HashMap<>();
                for(int i=0;i<urlParamArrays.size();i++){
                    JSONObject obj=urlParamArrays.getJSONObject(i);
                    String codeField="";
                    String valueField="";
                    if(obj.containsKey("code")){
                        codeField=obj.getString("code");
                    }
                    if(obj.containsKey("value")){
                        valueField=obj.getString("value");
                    }
                    if(StringUtil.isNotEmpty(valueField)){
                        valueField= StringUtil.parseKeyWord(valueField,ddSet);
                    }
                    if(StringUtil.isNotEmpty(codeField)){
                        urlParams.put(codeField,valueField);
                    }
                }
                String resObjStr= HttpUtil.post(url,urlParams);
                JSONObject resObj= JSONObject.parseObject(resObjStr);
            }else if("DS".equals(tqfs)){
                String tqdsCode=dsBean.getStr("DATASOURCE_CODE");
                Map<String,Object> requestParams=new HashMap<>();
                for(String key:dsParams.keySet()){
                    requestParams.put(key,dsParams.get(key));
                }
                lists=dataSourceRpcService.executeForRpc(tqdsCode,requestParams,-1);
            }
            for(DynaBean field:officeData.getFields()){
                String configInfo=field.getStr("FIELD_CONFIGINFO");
                if("LISTDIC".equals(field.getStr("FIELD_TYPE")) && StringUtil.isNotEmpty(configInfo)){
                    String ddCode=configInfo.split(",")[0];
                    if(!dzValues.containsKey(ddCode)) {
                        DynaBean dictionary = metaResourceService.selectOneByNativeQuery("JE_CORE_DICTIONARY", NativeQuery.build().eq("DICTIONARY_DDTYPE", DDType.LIST) .eq("DICTIONARY_DDCODE", ddCode)
                                .apply("and (SY_STATUS = '' or SY_STATUS = '1')"));
                        List<DynaBean> dicItems=metaResourceService.selectByTableCodeAndNativeQuery("JE_CORE_DICTIONARYITEM",NativeQuery.build().eq("SY_FLAG", "1")
                                .ne("SY_NODETYPE", "ROOT")
                                .eq("DICTIONARYITEM_DICTIONARY_ID", dictionary.getStr("JE_CORE_DICTIONARY_ID")).orderByAsc("SY_ORDERINDEX"));

//                        List<DictionaryItemVo> itemVos=dictionaryRpcService.getDicList(ddCode,new Query(),false);
                        List<JSONTreeNode> dzLists=new ArrayList<>();
                        for(DynaBean itemVo:dicItems){
                            JSONTreeNode node=new JSONTreeNode();
                            node.setId(itemVo.getStr("JE_CORE_DICTIONARYITEM_ID"));
                            node.setText(itemVo.getStr("DICTIONARYITEM_ITEMNAME"));
                            node.setCode(itemVo.getStr("DICTIONARYITEM_ITEMCODE"));
                            dzLists.add(node);
                        }
//                        List<JSONTreeNode> dzLists = dictionaryRpcService.getAllTyepDdListItems(ddCode, new HashMap<>(), new QueryInfo(), false);
                        List<DynaBean> dicLists = new ArrayList<>();
                        for (JSONTreeNode dzItem : dzLists) {
                            DynaBean bean = new DynaBean();
                            bean.set("text", dzItem.getText());
                            bean.set("code", dzItem.getCode());
                            bean.set("id", dzItem.getId());
                            bean.set("bean", dzItem.getBean());
                            dicLists.add(bean);
                        }
                        dzValues.put(ddCode, dicLists);
                        jeOfficeVo.setDzValues(dzValues);
                    }
                }else if("LISTQUERY".equals(field.getStr("FIELD_TYPE")) && StringUtil.isNotEmpty(configInfo)){
                    String tCode=configInfo.split(",")[0];
                    if(!dzValues.containsKey(tCode)) {
                        String tWhere=field.getStr("FIELD_DZWHERE","");
                        tWhere= StringUtil.parseKeyWord(tWhere,ddSet);
                        List<DynaBean> dzLists=metaService.selectBeanSql(tCode,tWhere);
                        dzValues.put(tCode, dzLists);
                        jeOfficeVo.setDzValues(dzValues);
                    }
                }
                if(StringUtil.isNotEmpty(field.getStr("FIELD_VALUE"))){
                    field.set("FIELD_VALUE", StringUtil.parseKeyWord(field.getStr("FIELD_VALUE"),ddSet));
                }
            }
            int index=1;
            for(DynaBean bean:lists){
                bean.set("rownumber",index);
                index++;
                //处理带值
                for(DynaBean field:officeData.getFields()){
                    String configInfo=field.getStr("FIELD_CONFIGINFO");
                    String ddCode="";
                    String[] thisFields=null;
                    String[] targerFields=null;
                    if(ArrayUtils.contains(new String[]{"LISTDIC","LISTQUERY"},field.getStr("FIELD_TYPE")) && StringUtil.isNotEmpty(configInfo)){
                        ddCode=configInfo.split(",")[0];
                        if(configInfo.split(",").length<=1)continue;
                        thisFields=configInfo.split(",")[1].split("~");
                        targerFields=configInfo.split(",")[2].split("~");
                    }
                    if("1".equals(field.getStr("FIELD_DZ")) && StringUtil.isNotEmpty(field.getStr("FIELD_DZCONFIG")) && StringUtil.isNotEmpty(ddCode)){
                        String[] dzConfigs=field.getStr("FIELD_DZCONFIG").split(",");
                        List<DynaBean> dzLists=jeOfficeVo.getDzValues().get(ddCode);
                        for(DynaBean dicInfo:dzLists) {
                            int flagCs = 0;
                            for (String dzConfig : dzConfigs) {
                                if (StringUtil.isEmpty(dzConfig)) {
                                    flagCs++;
                                    continue;
                                }
                                String thisField = dzConfig.split("~")[0];
                                String targerField = dzConfig.split("~")[1];
                                if (bean.getStr(thisField).equals(dicInfo.getStr(targerField))) {
                                    flagCs++;
                                }
                            }
                            if (flagCs == dzConfigs.length) {
                                for(int i=0;i<thisFields.length;i++){
                                    bean.set(thisFields[i],dicInfo.getStr(targerFields[i]));
                                }
                            }
                        }
                    }
                }
                if("1".equals(dsBean.getStr("DATA_WFDATA"))){
                    String tCode=dsBean.getStr("DATA_TABLECODE");
                    String tPkCode= "";
                    if(StringUtil.isNotEmpty(tCode)) {
                        tPkCode = beanService.getPKeyFieldNamesByTableCode(tCode);
                    }
                    if(ArrayUtils.contains(new String[]{"WAIT","ENDED"},bean.getStr("SY_AUDFLAG"))){
                        List<CirculationHistoryVo> logs=currentUserTaskRpcService.getCirculationHistory(bean.getStr(tPkCode));

                        for(CirculationHistoryVo log:logs){
                            String endTime="";
                            String endDate="";
                            String startTime="";
                                //获取流程动作
                            if(StringUtil.isEmpty(log.getOperationType()))continue;
                            if(!ArrayUtils.contains(new String[]{"SUBMIT","SPONSOR"},log.getOperationType())){
                                continue;
                            }
                            List<String> assignees=log.getAssignees();
                            if(assignees.size()<=0)continue;
                            if(StringUtil.isNotEmpty(log.getEndTime())) {
                                endTime=log.getEndTime();
                                endDate=DateUtils.formatDate(DateUtils.getDate(log.getEndTime(),DateUtils.DAFAULT_DATETIME_FORMAT),DateUtils.DAFAULT_DATE_FORMAT);
                            }
                            if(StringUtil.isNotEmpty(log.getStartTime())) {
                                startTime=log.getStartTime();
                            }
                            bean.set("WF_"+log.getNodeName()+"_task",log.getNodeName());
                            bean.set("WF_"+log.getNodeName()+"_user",assignees.get(0));
                            String assigneeId="";
                              String comment="";
                            List<CommentVo> commentVos=log.getComments();
                            if(commentVos.size()>0){
                                assigneeId=commentVos.get(0).getUserId();
                                comment=commentVos.get(0).getComment();
                            }
                            bean.set("WF_"+log.getNodeName()+"_seal","");
                             if(StringUtil.isNotEmpty(assigneeId)) {
                                DynaBean seal=jeSealService.getSealInfo(assignees.get(0),"USERID","0");
                                if(seal!=null){
                                    bean.set("WF_"+log.getNodeName()+"_seal",seal.getStr("SEAL_FILE"));
                                }
                             }
                            else{
                                bean.set("WF_"+log.getNodeName()+"_seal","");
                            }
                            bean.set("WF_"+log.getNodeName()+"_start",startTime);
                            bean.set("WF_"+log.getNodeName()+"_time",endTime);
                            bean.set("WF_"+log.getNodeName()+"_date",endDate);
                            bean.set("WF_"+log.getNodeName()+"_comment",comment);
                        }
                    }
                }
            }
            if(lists.size()>0){
                if("bean".equals(officeData.getType())){
                    DynaBean dynaBean=lists.get(0);
                    ddSet.addAll(OfficeUtil.getDynaMap(dynaBean).entrySet());
                    dsParams.putAll(OfficeUtil.getDynaMap(dynaBean));
                    officeData.setDynaBean(dynaBean);
                }
            }
            officeData.setLists(lists);
        }

    }

    @Override
    public void doExecEvent(JeOfficeVo jeOfficeVo, String type) {
        String beanName="";
        String beanMethod="";
        DynaBean docBean=jeOfficeVo.getDocConfig();
        if("before".equals(type)){
            beanName=docBean.getStr("BEFORE_BEAN");
            beanMethod=docBean.getStr("BEFORE_METHOD");
        }else if("after".equals(type)){
            beanName=docBean.getStr("AFTER_BEAN");
            beanMethod=docBean.getStr("AFTER_METHOD");
        }else if("init".equals(type)){
            beanName=docBean.getStr("INIT_BEAN");
            beanMethod=docBean.getStr("INIT_METHOD");
        }
        if(StringUtil.isNotEmpty(beanName) && StringUtil.isNotEmpty(beanMethod)) {
            Object bean = SpringContextHolder.getBean(beanName);
            ReflectionUtils.getInstance().invokeMethod(bean, beanMethod, new Object[]{jeOfficeVo});
        }
    }

    @Override
    public FileVO transformVO(InternalFileBO fileBO) {
        FileVO vo = new FileVO();
        vo.setFileKey(fileBO.getFileKey());
        vo.setRelName(fileBO.getRelName());
        vo.setFullUrl(fileBO.getFullUrl());
        vo.setSuffix(fileBO.getSuffix());
        vo.setHasThumbnail(StringUtils.isNotBlank(fileBO.getThumbnail()));
        vo.setSize(fileBO.getSize());
        vo.setCreateTime(fileBO.getCreateTime());
        vo.setCreateTimeStr(DateUtils.formatDateTime(fileBO.getCreateTime()));
        vo.setDicCode(fileBO.getDicCode());
        vo.setDicId(fileBO.getDicId());
        vo.setDicName(fileBO.getDicName());
        vo.setRemarks(fileBO.getRemarks());
        vo.setCreateUserDeptName(fileBO.getCreateUserDeptName());
        vo.setCreateUserName(fileBO.getCreateUserName());
        return vo;
    }
}
